﻿Imports System.Text

Friend Module InteractiveShell
    ''' <summary>
    ''' Used to enter the Interactive Shell Main loop
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub ShellMain()
        AddLog()
        AddLogV("Interactive Compilation Shell")
        AddLog("For help write 'help'")

        Dim shellBreak As Boolean = False
        Dim shellCompile As Boolean = False
        Dim shellSimulating As Boolean = False

RepeatWaitCommand:
        Dim instruction() As String
        instruction = WaitForCommand()

        If instruction Is Nothing Then GoTo RepeatWaitCommand
        If Trim(instruction(0)) = "" Then GoTo RepeatWaitCommand

        Select Case LCase(instruction(0))
            Case "status", "sta"
                ' Displays status about the current configuration
                Try
                    AddLog()
                    AddLog("Displaying stats for the Current Package")
                    If CurrentConfiguration.InputFilename Is Nothing Then
                        AddLog("  No files added yet.")
                    Else
                        Dim i As Integer
                        AddLog("  <" & Configuration.CurrentConfiguration.InputFilename.Count & "> files added.")
                        For i = 0 To Configuration.CurrentConfiguration.InputFilename.Count - 1
                            AddLog("<" & i & "> " & CurrentConfiguration.InputFilename(i), False, False)
                        Next
                    End If
                    AddLog("Output: " & CurrentConfiguration.OutputFilename)
                    AddLog("Protocol: " & CurrentConfiguration.OutputProtocol)
                    AddLogV("Stats dump complete.")
                Catch ex As Exception
                    AddLog("Exception found while performing operation!")
                    AddLog("   EX: " & ex.Message)
                End Try
            Case "include", "inc"
                ' Include a source file to the project
                Try
                    Dim filename As String
                    filename = ConsolidateParameters(instruction, 1, instruction.Length - 1, " ")

                    Dim fi As New IO.FileInfo(filename)
                    If fi.Exists = False Then
                        AddLog("Cant find the specified file.")
                        Exit Try
                    End If

                    If IsItemStoredInList(filename, CurrentConfiguration.InputFilename) Then
                        AddLog("File already added. Ignoring")
                    Else
                        Dim newindex As Integer
                        If CurrentConfiguration.InputFilename Is Nothing Then newindex = 0 Else newindex = Configuration.CurrentConfiguration.InputFilename.Count
                        AddLogV("Including file <" & filename & "> as index <" & newindex & ">...")

                        CurrentConfiguration.InputFilename.Add(filename)
                        AddLogV("Added.")
                    End If
                Catch ex As Exception
                    AddLog("Exception found while performing include operation!")
                    AddLog("   EX: " & ex.Message)
                End Try
            Case "includepattern", "incpat", "ipa", "includepatternrecursive", "incpatrec", "ipr"
                ' Include a sourcefile list thats the result of searching with an specified pattern (eg *.ascii)
                ' The last 3 segments specifies a Recursive Search
                Dim recursive As Boolean = False
                Select Case LCase(instruction(0))
                    Case "includepatternrecursive", "incpatrec", "ipr"
                        recursive = True
                        AddLog("Performing a Recursive Query...")
                    Case Else
                        recursive = False
                End Select
                Try
                    Dim pattern As String
                    pattern = ConsolidateParameters(instruction, 1, instruction.Length - 1, " ")
                    Dim filenames() As String
                    Dim path As String
                    Dim components() As String = Split(pattern, "\")
                    If components.Length = 0 Then
                        AddLog("Invalid search pattern specified.")
                        Exit Try
                    End If
                    Dim discardPath As Boolean = False
                    If components.Length = 1 Then
                        ' Only a pattern specified
                        pattern = components(0)
                        If recursive Then
                            filenames = IO.Directory.GetFiles(IO.Directory.GetCurrentDirectory, pattern, IO.SearchOption.AllDirectories)
                        Else
                            filenames = IO.Directory.GetFiles(IO.Directory.GetCurrentDirectory, pattern)
                        End If
                        discardPath = True
                    Else
                        ' Path + Pattern specified
                        path = ConsolidateParameters(components, 0, components.Length - 2, "\")
                        pattern = components(components.Length - 1)
                        Dim di As New IO.DirectoryInfo(path)
                        If di.Exists = False Then
                            AddLog("Specified directory not found.")
                            Exit Try
                        End If
                        path = di.FullName
                        If recursive Then
                            filenames = IO.Directory.GetFiles(path, pattern, IO.SearchOption.AllDirectories)
                        Else
                            filenames = IO.Directory.GetFiles(path, pattern)
                        End If
                        discardPath = False
                    End If

                    If filenames Is Nothing Then
                        AddLog("No files found.")
                        Exit Try
                    End If
                    If filenames.Length = 0 Then
                        AddLog("No files found.")
                        Exit Try
                    End If

                    Dim i As Integer
                    For i = 0 To filenames.Length - 1
                        Dim file As String = filenames(i)
                        file = Trim(file)
                        If Not file = "" Then
                            If discardPath = True Then
                                Dim cfname As String
                                If recursive Then
                                    cfname = Replace(file, IO.Directory.GetCurrentDirectory & "\", "", , 1)
                                    If Not IsItemStoredInList(cfname, CurrentConfiguration.InputFilename) Then
                                        CurrentConfiguration.InputFilename.Add(cfname)
                                    End If
                                Else
                                    Dim fi As New IO.FileInfo(file)
                                    cfname = fi.Name
                                    If Not IsItemStoredInList(cfname, CurrentConfiguration.InputFilename) Then
                                        CurrentConfiguration.InputFilename.Add(cfname)
                                    End If
                                End If
                            Else
                                If Not IsItemStoredInList(file, CurrentConfiguration.InputFilename) Then
                                    CurrentConfiguration.InputFilename.Add(file)
                                End If
                            End If
                        End If
                    Next

                    AddLog(filenames.Length & " files found and added.")
                Catch ex As Exception
                    AddLog("Exception found while performing include operation!")
                    AddLog("   EX: " & ex.Message)
                End Try
            Case "exclude", "exc"
                ' Excludes a source file from the project
                If CurrentConfiguration.InputFilename Is Nothing Then Exit Select

                Try
                    Dim fileIndex As String
                    fileIndex = instruction(1)
                    AddLogV("Excluding <" & fileIndex & ": " & CurrentConfiguration.InputFilename(fileIndex) & ">")
                    CurrentConfiguration.InputFilename.RemoveAt(fileIndex)
                Catch ex As Exception
                    AddLog("Exception found while performing exclude operation!")
                    AddLog("   EX: " & ex.Message)
                End Try
            Case "moveup", "mup"
                ' Move a source file UP from the compilation order
                ' call to swap(item-1,item)
                If CurrentConfiguration.InputFilename Is Nothing Then Exit Select
                If Configuration.CurrentConfiguration.InputFilename.Count < 2 Then Exit Select

                Try
                    Dim startIndex As Long
                    Dim endIndex As Long
                    startIndex = instruction(1)
                    endIndex = startIndex - 1
                    AddLogV("Moving <" & startIndex & ": " & CurrentConfiguration.InputFilename(startIndex) & "> to <" & endIndex & ">")
                    PerformListMoveOperation(CurrentConfiguration.InputFilename, startIndex, endIndex)
                    AddLogV("Done.")
                Catch ex As Exception
                    AddLog("Exception found while performing move operation!")
                    AddLog("   EX: " & ex.Message)
                End Try
            Case "movedown", "mdo"
                ' Move a source file DOWN from the compilation order
                'call to swap(item,item-1)
                If CurrentConfiguration.InputFilename Is Nothing Then Exit Select
                If Configuration.CurrentConfiguration.InputFilename.Count < 2 Then Exit Select

                Try
                    Dim startIndex As Long
                    Dim endIndex As Long
                    startIndex = instruction(1)
                    endIndex = startIndex + 1
                    AddLogV("Moving <" & startIndex & ": " & CurrentConfiguration.InputFilename(startIndex) & "> to <" & endIndex & ">")
                    PerformListMoveOperation(CurrentConfiguration.InputFilename, startIndex, endIndex)
                    AddLogV("Done.")
                Catch ex As Exception
                    AddLog("Exception found while performing move operation!")
                    AddLog("   EX: " & ex.Message)
                End Try
            Case "swap", "swp"
                ' Swaps a source file position inside the compilation order with other file
                If CurrentConfiguration.InputFilename Is Nothing Then Exit Select
                If Configuration.CurrentConfiguration.InputFilename.Count < 2 Then Exit Select

                Try
                    Dim startIndex As Long
                    Dim endIndex As Long
                    startIndex = instruction(1)
                    endIndex = instruction(2)
                    AddLogV("Swapping <" & startIndex & ": " & CurrentConfiguration.InputFilename(startIndex) & "> to <" & endIndex & ": " & CurrentConfiguration.InputFilename(endIndex) & ">")
                    Dim tempItem As String
                    tempItem = CurrentConfiguration.InputFilename(startIndex)
                    CurrentConfiguration.InputFilename(startIndex) = CurrentConfiguration.InputFilename(endIndex)
                    CurrentConfiguration.InputFilename(endIndex) = tempItem
                    AddLogV("Done.")
                Catch ex As Exception
                    AddLog("Exception found while performing swap operation!")
                    AddLog("   EX: " & ex.Message)
                End Try
            Case "moveto", "mto"
                ' Moves a source file position inside the compilation order to the specified index
                If CurrentConfiguration.InputFilename Is Nothing Then Exit Select
                If Configuration.CurrentConfiguration.InputFilename.Count < 2 Then Exit Select

                Try
                    Dim startIndex As Long
                    Dim endIndex As Long
                    startIndex = instruction(1)
                    endIndex = instruction(2)
                    AddLogV("Moving <" & startIndex & ": " & CurrentConfiguration.InputFilename(startIndex) & "> to <" & endIndex & ">")
                    PerformListMoveOperation(CurrentConfiguration.InputFilename, startIndex, endIndex)
                    AddLogV("Done.")
                Catch ex As Exception
                    AddLog("Exception found while performing move operation!")
                    AddLog("   EX: " & ex.Message)
                End Try
            Case "movetoend", "mte"
                ' Moves a source file position to the end of the compilation order
                If CurrentConfiguration.InputFilename Is Nothing Then Exit Select
                If Configuration.CurrentConfiguration.InputFilename.Count < 2 Then Exit Select

                Try
                    Dim startIndex As Long
                    Dim endIndex As Long
                    startIndex = instruction(1)
                    endIndex = Configuration.CurrentConfiguration.InputFilename.Count - 1
                    AddLogV("Moving <" & startIndex & ": " & CurrentConfiguration.InputFilename(startIndex) & "> to <" & endIndex & ">")
                    PerformListMoveOperation(CurrentConfiguration.InputFilename, startIndex, endIndex)
                    AddLogV("Done.")
                Catch ex As Exception
                    AddLog("Exception found while performing move operation!")
                    AddLog("   EX: " & ex.Message)
                End Try
            Case "movetostart", "mts"
                ' Moves a source file position to the start of the compilation order
                If CurrentConfiguration.InputFilename Is Nothing Then Exit Select
                If Configuration.CurrentConfiguration.InputFilename.Count < 2 Then Exit Select

                Try
                    Dim startIndex As Long
                    Dim endIndex As Long
                    startIndex = instruction(1)
                    endIndex = 0
                    AddLogV("Moving <" & startIndex & ": " & CurrentConfiguration.InputFilename(startIndex) & "> to <" & endIndex & ">")
                    PerformListMoveOperation(CurrentConfiguration.InputFilename, startIndex, endIndex)
                    AddLogV("Done.")
                Catch ex As Exception
                    AddLog("Exception found while performing move operation!")
                    AddLog("   EX: " & ex.Message)
                End Try
            Case "sort", "srt"
                ' Sorts the File List
                AddLog("Sorting file list. Please wait...")
                CurrentConfiguration.InputFilename.Sort()
                AddLog("File list sorting complete.")
            Case "flags", "flg", "flag"
                ' Retrieves or sets the flags of the package
                If instruction.Length = 1 Then
                    ' Show all flags
                    Dim flags() As KeyValuePair(Of String, String)
                    flags = GetFlags()

                    If (flags Is Nothing) OrElse (flags.Length < 1) Then
                        AddLog("No flags specified.")
                    Else
                        AddLog("Specified Flags")
                        For Each x In flags
                            AddLog(" " & x.Key & "=" & x.Value)
                        Next
                    End If
                Else
                    Dim flagInstruction As String = ConsolidateParameters(instruction, 1, instruction.Length - 1, " ")
                    Dim flagTmp() As String = Split(flagInstruction, "=")

                    If flagTmp.Length > 2 Then
                        AddLog("Error!: Malformed flag instruction. More than one equal sign found")
                        AddLog("   Get Syntax:   flag key")
                        AddLog("   Set Syntax:   flag key=value")
                    ElseIf flagTmp.Length = 1 Then
                        ' Get Flag

                        If HasFlag(flagInstruction) Then
                            AddLog("Flag <" & flagInstruction & ">=<" & GetFlag(flagInstruction, "") & ">")
                        Else
                            AddLog("Flag <" & flagInstruction & "> is not defined.")
                        End If
                    Else
                        ' Set Flag
                        SetFlag(flagTmp(0), flagTmp(1))
                    End If
                End If
            Case "delflag", "dflg", "deflag"
                ' Deletes an specified Flag from the store

                If instruction.Length = 1 Then
                    AddLog("Error: No flag specified for deletion.")
                    AddLog(" Syntax:  deflag key1 key2 key3 ... keyn")
                    AddLog(" Use Plural to remove all flags")
                Else
                    Dim i As Integer
                    For i = 1 To instruction.Length - 1
                        RemoveFlag(instruction(i))
                    Next
                End If
            Case "delflags", "dflgs", "deflags"
                ' Deletes all specified Flags
                CurrentConfiguration.Flags.Clear()
                AddLog("Flags store deleted.")
            Case "extradata", "xtr"
                ' Retrieves or sets the Extra data defined for the current package
                AddLog("NOT SUPPORTED YET!")
            Case "description", "des"
                ' Retrieves or sets the Description of the current package
                Try
                    AddLog()
                    If instruction.Length = 1 Then
                        ' Get
                        AddLog("Package Description:")
                        AddLog(CurrentConfiguration.PackageDescription, False, False)
                    Else
                        ' Set
                        AddLogV("Setting new configuration...")
                        AddLogV("Previous size: " & CurrentConfiguration.PackageDescription.Length)
                        Dim newDescription As String
                        newDescription = ConsolidateParameters(instruction, 1, instruction.Length - 1, " ")
                        CurrentConfiguration.PackageDescription = newDescription
                        AddLogV("Done. New size: " & CurrentConfiguration.PackageDescription.Length)
                    End If
                Catch ex As Exception
                    AddLog("Exception found while performing operation!")
                    AddLog("   EX: " & ex.Message)
                End Try
            Case "output", "out"
                ' Retrieves or sets the filename of the Output file
                Try
                    If instruction.Length = 1 Then
                        ' Get
                        AddLog("Output file: " & CurrentConfiguration.OutputFilename)
                    Else
                        ' Set
                        Dim newOutput As String
                        AddLogV("Setting new output filename...")
                        AddLogV("Previous was: " & CurrentConfiguration.OutputFilename)
                        newOutput = ConsolidateParameters(instruction, 1, instruction.Length - 1, " ")
                        CurrentConfiguration.OutputFilename = newOutput
                        AddLogV("Done. New output filename is: " & CurrentConfiguration.OutputFilename)
                    End If
                Catch ex As Exception
                    AddLog("Exception found while performing operation!")
                    AddLog("   EX: " & ex.Message)
                End Try
            Case "lookup", "lup"
                ' Lookups for a filename inside the source array and returns every item that match the query
                If CurrentConfiguration.InputFilename Is Nothing Then Exit Select

                Try
                    AddLog()
                    Dim query As String
                    query = ConsolidateParameters(instruction, 1, instruction.Length - 1, " ")
                    Dim i As Long
                    For i = 0 To Configuration.CurrentConfiguration.InputFilename.Count - 1
                        If LCase(CurrentConfiguration.InputFilename(i)) Like LCase(query) Then
                            AddLog("   " & i & ": " & CurrentConfiguration.InputFilename(i))
                        End If
                    Next
                    AddLog("Displayed matches for <" & query & ">")
                Catch ex As Exception
                    AddLog("Exception found while performing lookup operation!")
                    AddLog("   EX: " & ex.Message)
                End Try
            Case "clear", "clr"
                ' Clears everything and starts from an empty package
                Try
                    AddLogV("Clearing buffers...")
                    With CurrentConfiguration
                        .InputFilename.Clear()
                        .OutputFilename = ""
                        .OutputProtocol = ""
                        .PackageDescription = ""
                    End With
                    AddLog("Cleared.")
                Catch ex As Exception
                    AddLog("Exception found while performing cleanup operation!")
                    AddLog("   EX: " & ex.Message)
                End Try
            Case "protocol", "prt"
                ' Retrieves or set the protocol that must be used to write the package
                Try
                    If instruction.Length = 1 Then
                        ' Get
                        AddLog("Output protocol: " & CurrentConfiguration.OutputProtocol)
                    Else
                        ' Set
                        Dim newProtocol As String
                        AddLogV("Setting new output protocol...")
                        AddLogV("Previous was: " & CurrentConfiguration.OutputProtocol)
                        newProtocol = ConsolidateParameters(instruction, 1, instruction.Length - 1, " ")
                        CurrentConfiguration.OutputProtocol = newProtocol
                        AddLogV("Done. New output protocol is: " & CurrentConfiguration.OutputProtocol)
                    End If
                Catch ex As Exception
                    AddLog("Exception found while performing operation!")
                    AddLog("   EX: " & ex.Message)
                End Try
            Case "shadow", "sdw"
                ' Sets properties for shadowing the specified package
                Try
                    If instruction.Length = 1 Then
                        ' Print Help
                        AddLog("Syntax: shadow <packageName> [convention] [startingIndex]")
                    Else
                        ' Set properties
                        Dim newOutput As String
                        AddLogV("Setting new output filename...")
                        AddLogV("Previous was: " & CurrentConfiguration.OutputFilename)
                        Select Case instruction.Length
                            Case 2
                                newOutput = Compilers.GetNextShadowFilenameForPackage(instruction(1), Nothing, 0)
                            Case 3
                                newOutput = Compilers.GetNextShadowFilenameForPackage(instruction(1), instruction(2), 0)
                            Case Else
                                newOutput = Compilers.GetNextShadowFilenameForPackage(instruction(1), instruction(2), instruction(3))
                        End Select

                        CurrentConfiguration.OutputFilename = newOutput
                        AddLogV("Done. New output filename is: " & CurrentConfiguration.OutputFilename)
                        Configuration.CurrentConfiguration.ShadowMode = True
                        AddLog("Shadow mode is now enabled. ""delete"" entries are now valid")
                    End If
                Catch ex As Exception
                    AddLog("Exception found while performing operation!")
                    AddLog("   EX: " & ex.Message)
                End Try
            Case "adddel", "srm"
                ' Adds a deletion entry for Shadow packages
                Try
                    If instruction.Length = 1 Then
                        ' Print Help and Deletion entries
                        AddLog("Deletion Entries:")
                        If Configuration.CurrentConfiguration.ShadowDeleteEntries.Count > 0 Then
                            Dim i As Long
                            For i = 0 To Configuration.CurrentConfiguration.ShadowDeleteEntries.Count - 1
                                AddLog("  " & i & "* " & Configuration.CurrentConfiguration.ShadowDeleteEntries(i))
                            Next

                            AddLog()
                            AddLog(Configuration.CurrentConfiguration.ShadowDeleteEntries.Count & " total entries.")
                        Else
                            AddLog(" -- No Shadow deletion entries added yet --")
                        End If

                        AddLog()
                        AddLog("Syntax: adddel <filename>")
                    Else
                        ' Add Deletion entry
                        Dim name As String = instruction(1)
                        name = Trim(name)
                        name = Replace(name, "/", "\")
                        If name(0) = "\" Then name = name.Substring(1) ' Remove any leading "\"
                        If name(name.Length - 1) = "\" Then name = name.Substring(0, name.Length - 1) ' Remove any trailing "\"
                        name = Trim(name)

                        ' Check duplicate
                        Dim i As Long
                        Dim lcname As String = name.ToLowerInvariant()
                        For i = 0 To Configuration.CurrentConfiguration.ShadowDeleteEntries.Count - 1
                            If Configuration.CurrentConfiguration.ShadowDeleteEntries(i).ToLowerInvariant() = lcname Then
                                AddLog("Warning - A similar deletion entry that points to the same filename has been already added")
                                Exit Try
                            End If
                        Next

                        ' Add entry
                        Configuration.CurrentConfiguration.ShadowDeleteEntries.Add(name)
                        AddLogV("Added deletion entry for file <" & name & ">")
                    End If
                Catch ex As Exception
                    AddLog("Exception found while performing operation!")
                    AddLog("   EX: " & ex.Message)
                End Try
            Case "cleardel"
                ' Clears the deletion table for shadow packages
                Configuration.CurrentConfiguration.ShadowDeleteEntries.Clear()
                AddLog("Deletion table for shadow packages has been cleared.")
            Case "simulate", "sim"
                ' Starts a package simulation that calculates how much bytes will be readed, if the files are available for reading, and the size of the resulting package
                AddLog()
                AddLog(" --- SIM ---")
                shellBreak = True
                shellCompile = True
                shellSimulating = True
            Case "compile"
                ' Starts a compilation process
                AddLog()
                AddLog(" --- COMPILE ---")
                shellBreak = True
                shellCompile = True
                shellSimulating = False
            Case "exit"
                ' Exits the shell without performing any extra action
                AddLogV("Quitting Interactive shell...")
                shellBreak = True
                shellCompile = False
            Case Else
                AddLog("Unknown instruction <" & instruction(0) & ">")
        End Select

        If shellBreak = False Then GoTo RepeatWaitCommand
        If shellCompile = True Then
            ' Check protocol
            If Configuration.CurrentConfiguration.OutputProtocol = "" Then
                AddLog("No protocol specified. Aborted")
                shellBreak = False
                shellCompile = False
                shellSimulating = False
                GoTo RepeatWaitCommand
            End If

            ' Check compiler
            Dim xcompiler As Compilers.GenericCompiler = Nothing
            Dim i As Integer
            For i = 0 To Configuration.AvailableCompilers.Length - 1
                If UCase(CurrentConfiguration.OutputProtocol) = UCase(Configuration.AvailableCompilers(i).CompilerProtocol) Then
                    AddLogV("Compiler found for specified protocol.")
                    AddLogV(Configuration.AvailableCompilers(i).CompilerName)
                    xcompiler = Configuration.AvailableCompilers(i)
                End If
            Next
            If xcompiler Is Nothing Then
                AddLog("No compiler found for defined protocol. Remember that a protocol follows the syntax of 'M.m.b.r_x'")
                shellBreak = False
                shellCompile = False
                shellSimulating = False
                GoTo RepeatWaitCommand
            End If

            ' Yield for Simulation and Compilation
            shellBreak = False
            shellCompile = False
            If shellSimulating = True Then
                ' Simulate
                Dim returned As Arps.Compilation.Compilers.Commons.PackageCompilerSimulationResult
                returned = xcompiler.Simulate()
                Select Case returned.Code
                    Case Compilers.PackageCompilerSimulationResultCode.SimulationSucceeded
                        AddLog("Simulation passed!. OK to compile")
                    Case Else
                        AddLog("Simulation failed: <" & returned.Code & "> " & returned.Message)
                End Select
                shellSimulating = False
                GoTo RepeatWaitCommand
            Else
                ' Compile
                Dim returned As Compilers.Commons.PackageCompilationResult
                returned = xcompiler.Compile()
                Select Case returned.Code
                    Case Compilers.Commons.PackageCompilationResultCode.CompilationSucceeded
                        AddLog()
                        AddLog("Compilation complete!")
                        AddLog(returned.Statistics.PackedFiles & " files packed")
                        AddLog("Output size: " & Compilers.Commons.FormatSizeAsHumanReadable(returned.Statistics.OutputSize) & " @ " & Compilers.Commons.FormatSizeAsHumanReadable(returned.Statistics.PackedBytes))
                        AddLog("Started at: " & returned.Statistics.StartTime)
                        AddLog("Ended at: " & returned.Statistics.EndTime)
                        AddLog("Entire process took: " & returned.Statistics.TcsDiffTime)
                        AddLog("Buffer Avg: " & Compilers.Commons.FormatSizeAsHumanReadable(returned.Statistics.AverageBufferUsed) & "  Max: " & Compilers.Commons.FormatSizeAsHumanReadable(returned.Statistics.MaxBufferUsed) & "  Min: " & Compilers.Commons.FormatSizeAsHumanReadable(returned.Statistics.MinBufferUsed))
                        AddLog("Ticks Avg: " & Compilers.Commons.GetFormattedTime(New TimeSpan(returned.Statistics.AverageTicksPerIO)) & "  Max: " & Compilers.Commons.GetFormattedTime(New TimeSpan(returned.Statistics.MaxTicksPerIO)) & "  Min: " & Compilers.Commons.GetFormattedTime(New TimeSpan(returned.Statistics.MinTicksPerIO)))
                        AddLogV("Tick barrier: " & returned.Statistics.TickBarrier)
                        AddLogV("Tick length: " & returned.Statistics.TickLength)
                    Case Else
                        AddLog("Compilation failed: <" & returned.Code & "> " & returned.Message)
                        GoTo RepeatWaitCommand
                End Select
            End If
        Else
            ' WHEN ENTERING HERE, THE USER REQUESTED TO EXIT THE SHELL
            AddLog()
            AddLog()
            AddLog("---------------- QUIT")
        End If
        AddLog("Leaving shell...")
    End Sub

    ''' <summary>
    ''' Loops asking the user for a valid command
    ''' </summary>
    ''' <returns>An array containing a command and any parameters that represents a valid shell instruction</returns>
    ''' <remarks></remarks>
    Public Function WaitForCommand() As String()
        Dim instruction As String = ""
        Do While instruction = ""
            AddLog("acu\> ", True, False)
            If Console.KeyAvailable = True Then
                System.Threading.Thread.Sleep(100)
                Do Until Console.KeyAvailable = False
                    Console.ReadKey(True)
                Loop
            End If
            instruction = Console.ReadLine()
            If Trim(instruction) = "" Then instruction = ""
        Loop

        Dim segments As New List(Of String)(8)
        Dim i As Integer
        Dim strBuffer As New StringBuilder()
        Dim quoted As Boolean = False
        For i = 0 To instruction.Length - 1
            Dim curr As Char = instruction(i)
            Select Case curr
                Case """"c
                    quoted = Not quoted
                Case " "c
                    If quoted Then
                        strBuffer.Append(" "c)
                    Else
                        segments.Add(strBuffer.ToString())
                        strBuffer = New StringBuilder()
                    End If
                Case Else
                    strBuffer.Append(curr)
            End Select
        Next

        If strBuffer.Length > 0 Then
            segments.Add(strBuffer.ToString())
        End If

        Return segments.ToArray()
    End Function

    ''' <summary>
    ''' Moves an item inside an List of string to a new position
    ''' </summary>
    ''' <param name="lst">List that will be modified by Reference</param>
    ''' <param name="sourceItemIndex">Source index of the item that will be moved</param>
    ''' <param name="destItemIndex">Destination index where the item will be placed, if the index is used by another item, that item and everything after it will be moved down</param>
    ''' <remarks></remarks>
    Public Sub PerformListMoveOperation(ByRef lst As List(Of String), ByVal sourceItemIndex As Long, ByVal destItemIndex As Long)
        Dim output As List(Of String) = New List(Of String)(lst.Capacity)

        If lst Is Nothing Then Exit Sub
        If lst.Count < 1 Then Exit Sub
        If sourceItemIndex < 0 Then Exit Sub
        If destItemIndex >= lst.Count Then destItemIndex = lst.Count - 1

        If sourceItemIndex = destItemIndex Then Exit Sub

        Dim counter As Long = 0
        Dim arrayWalker As Long = 0
        Do Until counter > lst.Count - 1
            ' Check Walker position
            If arrayWalker = sourceItemIndex Then ' If its on the item that will be moved, Ignore it, increase walker but leave counter intact
                arrayWalker += 1
                Continue Do
            End If
            If arrayWalker = destItemIndex Then ' If its on the destination index, Copy the source index here, increase counter but leave walker intact
                output(counter) = lst(sourceItemIndex)
                counter += 1
                'arrayWalker += 1
                'Continue Do
            End If

            ' Normal loop, walker is not on Source Item neither Destination Item
            ' Copy the same item here, and increase both counter and walker
            output(counter) = lst(arrayWalker)
            counter += 1
            arrayWalker += 1
        Loop

        lst = output
    End Sub
    ' ''' <summary>
    ' ''' Remove an item from an array
    ' ''' </summary>
    ' ''' <param name="array">Array passed by reference from wich the item will be removed</param>
    ' ''' <param name="index">Index of the item to be removed</param>
    ' ''' <remarks></remarks>
    'Public Sub PerformArrayExcludeOperation(ByRef array() As String, ByVal index As Long)
    '    If array Is Nothing Then Exit Sub
    '    If array.Length = 1 Then array = Nothing : Exit Sub

    '    If index < 0 Then Exit Sub
    '    If index >= array.Length Then index = array.Length - 1

    '    Dim output() As String = Nothing
    '    Dim counter As Long
    '    For counter = 0 To array.Length - 1
    '        If Not counter = index Then
    '            If output Is Nothing Then
    '                ReDim output(0)
    '            Else
    '                ReDim Preserve output(output.Length)
    '            End If
    '            output(output.Length - 1) = array(counter)
    '        End If
    '    Next

    '    array = output
    '    Erase output
    'End Sub
    ''' <summary>
    ''' Searches if an item is already stored inside an specified List of strings
    ''' </summary>
    ''' <param name="search">String to search inside the List</param>
    ''' <param name="lst">List where the string will be search for</param>
    ''' <returns>True if the list already have the specified string, otherwise false</returns>
    ''' <remarks></remarks>
    Public Function IsItemStoredInList(ByVal search As String, ByRef lst As List(Of String)) As Boolean
        If lst.Count < 1 Then Return False

        Dim i As Integer
        Dim lsearch As String = search.ToLowerInvariant()
        For i = 0 To lst.Count - 1
            If lst(i).Length = lsearch.Length Then ' First check if the string is the same length
                If lst(i).ToLowerInvariant().Trim() = lsearch Then ' Perform string comparison
                    Return True
                End If
            End If
        Next

        Return False
    End Function
End Module
